﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.DirectoryServices;
using System.Configuration;
using shfa.snomtastic.data.business;

namespace shfa.snomtastic.data.security
{
    public class adSecurity
    {
        public AppConfig ac { get; set; }

        public adSecurity()
        {
            ac = new AppConfig();
        }

        [FlagsAttribute]
        private enum ADS_USER_FLAG_ENUM
        {
            ADS_UF_SCRIPT = 1,         // 0x1
            ADS_UF_ACCOUNTDISABLE = 2,         // 0x2
            ADS_UF_HOMEDIR_REQUIRED = 8,         // 0x8
            ADS_UF_LOCKOUT = 16,        // 0x10
            ADS_UF_PASSWD_NOTREQD = 32,        // 0x20
            ADS_UF_PASSWD_CANT_CHANGE = 64,        // 0x40
            ADS_UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED = 128,       // 0x80
            ADS_UF_TEMP_DUPLICATE_ACCOUNT = 256,       // 0x100
            ADS_UF_NORMAL_ACCOUNT = 512,       // 0x200
            ADS_UF_INTERDOMAIN_TRUST_ACCOUNT = 2048,      // 0x800
            ADS_UF_WORKSTATION_TRUST_ACCOUNT = 4096,      // 0x1000
            ADS_UF_SERVER_TRUST_ACCOUNT = 8192,      // 0x2000
            ADS_UF_DONT_EXPIRE_PASSWD = 65536,     // 0x10000
            ADS_UF_MNS_LOGON_ACCOUNT = 131072,    // 0x20000
            ADS_UF_SMARTCARD_REQUIRED = 262144,    // 0x40000
            ADS_UF_TRUSTED_FOR_DELEGATION = 524288,    // 0x80000
            ADS_UF_NOT_DELEGATED = 1048576,   // 0x100000
            ADS_UF_USE_DES_KEY_ONLY = 2097152,   // 0x200000
            ADS_UF_DONT_REQUIRE_PREAUTH = 4194304,   // 0x400000
            ADS_UF_PASSWORD_EXPIRED = 8388608,   // 0x800000
            ADS_UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION = 16777216   // 0x1000000
        } ;

        public bool isValidCredentials(string userName, string passWord)
        {


            DirectoryEntry testEntry = new DirectoryEntry(ac.Items["adRoot"], userName, passWord);
            try
            {
                object o = testEntry.NativeObject;
                return true;
            }
            catch
            {
                return false;
            }


     
        }


        public int badPasswordCount(string upn)
        {
            try
            {
                DirectoryEntry de = GetUserByUPN(upn);
                if (de != null)
                {
                    Int32 badPwdCount = 0;
                    Int32.TryParse(de.Properties["badPwdCount"].Value.ToString(), out badPwdCount);
                    return badPwdCount;
                }
            }
            catch { return -1; }

            return -1;
        }

        public bool accountlockedOut(string upn, DateTime passwordUpdate)
        {
            try
            {
                DirectoryEntry de = GetUserByUPN(upn);
                if (de != null)
                {
                    ADS_USER_FLAG_ENUM flags = (ADS_USER_FLAG_ENUM)de.Properties["userAccountControl"].Value;

                    if ((flags & ADS_USER_FLAG_ENUM.ADS_UF_PASSWD_NOTREQD) == ADS_USER_FLAG_ENUM.ADS_UF_PASSWD_NOTREQD)
                    {
                        return false;  // Can never be locked out
                    }
                    if ((flags & ADS_USER_FLAG_ENUM.ADS_UF_LOCKOUT) == ADS_USER_FLAG_ENUM.ADS_UF_LOCKOUT)
                    {
                        return true;
                    }
                    if ((flags & ADS_USER_FLAG_ENUM.ADS_UF_ACCOUNTDISABLE) == ADS_USER_FLAG_ENUM.ADS_UF_ACCOUNTDISABLE)
                    {
                        return true;
                    }
                    if ((flags & ADS_USER_FLAG_ENUM.ADS_UF_PASSWORD_EXPIRED) == ADS_USER_FLAG_ENUM.ADS_UF_PASSWORD_EXPIRED)
                    {
                        if ((flags & ADS_USER_FLAG_ENUM.ADS_UF_PASSWD_CANT_CHANGE) == ADS_USER_FLAG_ENUM.ADS_UF_PASSWD_CANT_CHANGE)
                        {
                            return false;  // password can't change
                        }
                        return true;
                    }
                    DateTime PasswordUpdateAD = common.GetDateFromLargeInteger(de.Properties["pwdLastSet"][0]);
                    if (PasswordUpdateAD > passwordUpdate)
                    {
                        return true;
                    }

                    // badpwdcount !cover password <> expired and badpassword entered
                    Int32 badPwdCount = 0;
                    Int32.TryParse(de.Properties["badPwdCount"].Value.ToString(), out badPwdCount);
                    if (badPwdCount > 0)
                    {
                        return true;
                    }
                }
            }
            catch { }

            return false;
        }


        public DirectoryEntry GetUserBySID(string userSID)
        {
            RijndaelEnhanced re = new RijndaelEnhanced();

            DirectoryEntry dentry = GetRootDE();

            DirectorySearcher dsearcher = new DirectorySearcher(dentry);
            dsearcher.Filter = ("(&(objectClass=user)(objectSID=" + userSID + "))");
            DirectoryEntry de = dsearcher.FindOne().GetDirectoryEntry();
            if (de != null)
            {
                return de;
            }

            return null;

        }

        public DirectoryEntry GetUserByUPN(string userName)
        {

            DirectoryEntry dentry = GetRootDE();

            try
            {
                DirectorySearcher dsearcher = new DirectorySearcher(dentry);
                dsearcher.Filter = ("(&(objectClass=user)(userPrincipalName=" + userName + "))");
                DirectoryEntry de = dsearcher.FindOne().GetDirectoryEntry();
                if (de != null)
                {
                    return de;
                }
            }
            catch
            {
                return null;
            }

            return null;
        }

        public DirectoryEntry GetUserBySamAccount(string samAccount)
        {
            RijndaelEnhanced re = new RijndaelEnhanced();
            DirectoryEntry dentry = GetRootDE();

            try
            {
                DirectorySearcher dsearcher = new DirectorySearcher(dentry);
                dsearcher.Filter = ("(&(objectClass=user)(sAMAccountName=" + samAccount + "))");
                DirectoryEntry de = dsearcher.FindOne().GetDirectoryEntry();
                if (de != null)
                {
                    return de;
                }
            }
            catch
            {
                return null;
            }

            return null;
        }

        public DirectoryEntry GetRootDE()
        {
            RijndaelEnhanced re = new RijndaelEnhanced();
            try
            {
                DirectoryEntry de = new DirectoryEntry
                {
                    Path = ac.Items["adRoot"],
                    Username = ac.Items["adLogin"],
                    Password = re.Decrypt(ac.Items["adPassword"])
                };
                return de;
            }
            catch
            {
                return new DirectoryEntry();

            }




        }

    }
}
